package sv.com.seguros.web.controller.asg;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;

import net.sf.json.JSONArray;

import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import sv.com.seguros.dto.asg.AsgPago;
import sv.com.seguros.exception.WebException;
import sv.com.seguros.web.controller.BaseController;
import sv.com.seguros.web.util.DBContext;
import sv.com.seguros.web.util.WebUtilidades;

@Controller
@RequestMapping("/abonos")
public class AsgAbonoController extends BaseController {

	private static final long serialVersionUID = 3834669882649782965L;
	
	@RequestMapping(value = "/view", method = {RequestMethod.GET, RequestMethod.POST})
	public String view(ModelMap model) {
		model.put(WebUtilidades.HEADER_TITLE, "ABONOS");
		try {
			model.put("ctgFormasPago", JSONArray.fromObject(DBContext.getCtgCatalogoDao().findAllActivesByCodigoAsArray(WebUtilidades.CTG_FORMA_PAGO_ABONO_PADRE)));
			model.put("ctgLugaresPago", JSONArray.fromObject(DBContext.getCtgCatalogoDao().findAllActivesByCodigoAsArray(WebUtilidades.CTG_LUGAR_PAGO_PADRE)));
			model.put("isReadOnly", WebUtilidades.isReadOnly(WebUtilidades.ROLE_ABONO));
			model.put("allowDelete", WebUtilidades.isAllowDelete(WebUtilidades.ROLE_ABONO));
		} catch (Exception e) {
			logger.error("Exception:", e);
		}
		return "aseguradora/abono/asgDetalleAbono";
	}
	
	@RequestMapping(value = "/doSearch", method = {RequestMethod.POST})
	public void doSearch(HttpServletResponse response,
			@ModelAttribute AsgSeguroForm asgSeguroForm){
		Map<String, Object> result = new HashMap<String, Object>();
		try {
			List<Object[]> list = DBContext.getAsgClienteDao().findForPayDetail(asgSeguroForm);
			result.put("totalResult", list.size());
			if(WebUtilidades.isEmptyList(list)) result.put("list", JSONArray.fromObject(list));
			else{
				result.put("list", JSONArray.fromObject(WebUtilidades.sublist(list, asgSeguroForm.getStart(), asgSeguroForm.getLimit())));
			}
		} catch (Exception e) {
			logger.error("Exception: ", e);
		}
		serializeObject(result, response);
	}
	
	@RequestMapping(value = "/findAllAsgPagos", method = {RequestMethod.POST})
	public void findAllAsgPagos(@RequestParam Long asgClienteId, HttpServletResponse response){
		Map<String, Object> result = new HashMap<String, Object>();
		try{
			result.put("pendientes", DBContext.getAsgAbonoDao().findAllPendientes(asgClienteId));
			result.put("pagos", DBContext.getAsgAbonoDao().findAllPagos(asgClienteId));
			result.put(SUCCESS, true);
			result.put(MESSAGE, "Datos obtenidos");
		}catch(WebException e){
			logger.error("Exception:", e);
			result.put(FAILURE, true);
			result.put(MESSAGE, e.getExceptionMessage());
		}catch(Exception e){
			logger.error("Exception:", e);
			result.put(FAILURE, true);
			result.put(MESSAGE, DEFAULT_ERROR_MESSAGE);
		}
		serializeObject(result, response);
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/generatePayment", method = {RequestMethod.POST})
	public void generatePayment(
			@ModelAttribute AsgPago asgPago,
			@RequestParam Long asgClienteId,
			@RequestParam String jsonString,
			HttpServletResponse response){
		Map<String, Object> result = new HashMap<String, Object>();
		try{
			List<Long> asgAbonosId = (List<Long>) JSONArray.toCollection(JSONArray.fromObject(jsonString), Long.class);
			DBContext.getAsgPagoService().generatePay(asgPago, asgAbonosId);
			result.put("asgPagoId", asgPago.getAsgPagoId());
			result.put("pendientes", DBContext.getAsgAbonoDao().findAllPendientes(asgClienteId));
			result.put("pagos", DBContext.getAsgAbonoDao().findAllPagos(asgClienteId));
			result.put(SUCCESS, true);
			result.put(MESSAGE, UPDATED_DATA);
		}catch(WebException e){
			logger.error("Exception:", e);
			result.put(FAILURE, true);
			result.put(MESSAGE, e.getExceptionMessage());
		}catch(Exception e){
			logger.error("Exception:", e);
			result.put(FAILURE, true);
			result.put(MESSAGE, DEFAULT_ERROR_MESSAGE);
		}
		serializeObject(result, response);
	}
	
	@RequestMapping(value = "/reciboProvicional", method = {RequestMethod.GET, RequestMethod.POST})
	public void reciboProvicional(HttpServletResponse response, @RequestParam Long asgPagoId) {
		FopFactory fopFactory = FopFactory.newInstance();
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		try {
			String fopXml = WebUtilidades.getDocumentStructures("reciboProvicional.master");
			String logo = Thread.currentThread().getContextClassLoader().getResource("../../resources/images/crediseguro1.png") + "";
			fopXml = StringUtils.replace(fopXml, "${LOGO}", logo);
			
			List<Map<String, Object>> registers = DBContext.getAsgPagoDao().findReciboProvicional(asgPagoId);
			String asegudoraXml = WebUtilidades.getDocumentStructures("reciboProvicional.aseguradora");
			String cuotaXml = WebUtilidades.getDocumentStructures("reciboProvicional.cuotas");
			String cuotaTempXml = WebUtilidades.getDocumentStructures("reciboProvicional.cuotas");
			StringBuilder cuotas = new StringBuilder();
			boolean begin = true;
			String ctgAseguradoraNombre = null;
			for (Map<String, Object> register : registers) {
				cuotaTempXml = cuotaXml;
				if(begin){
					fopXml = StringUtils.replace(fopXml, "${RECIBIMOS}", (String) register.get("recibimos"));
					fopXml = StringUtils.replace(fopXml, "${NO_REFERENCIA}", (String) register.get("no_referencia"));
					fopXml = StringUtils.replace(fopXml, "${CANTIDAD}", (String) register.get("cantidad"));
					fopXml = StringUtils.replace(fopXml, "${COBRADOR}", (String) register.get("cobrador"));
					fopXml = StringUtils.replace(fopXml, "${OBSERVACION}", (String) register.get("observacion"));
					fopXml = StringUtils.replace(fopXml, "${LUGAR}", (String) register.get("lugar"));
					fopXml = StringUtils.replace(fopXml, "${FECHA}", (String) register.get("fecha"));
					fopXml = StringUtils.replace(fopXml, "${TOTAL_PAGAR}", 
							WebUtilidades.decimalFormat2Decimals.format(Double.parseDouble(WebUtilidades.trimToZero((String) register.get("total_pagar")))));
					fopXml = 
						StringUtils.replace(fopXml, "${FORMA_PAGO}", (String) register.get("forma_pago"));
					begin = false;
				}
				if(register.get("aseguradora") != null && !register.get("aseguradora").equals(ctgAseguradoraNombre)){
					ctgAseguradoraNombre = (String) register.get("aseguradora");
					cuotas.append(StringUtils.replace(asegudoraXml, "${ASEGURADORA}", ctgAseguradoraNombre));
				}
				cuotaTempXml = StringUtils.replace(cuotaTempXml, "${NO_CUOTA}", (String) register.get("no_cuota"));
				cuotaTempXml = StringUtils.replace(cuotaTempXml, "${VALOR_CUOTA}", 
						WebUtilidades.decimalFormat2Decimals.format(Double.parseDouble(WebUtilidades.trimToZero((String) register.get("valor_cuota")))));
				cuotaTempXml = StringUtils.replace(cuotaTempXml, "${VALOR_RECIBIDO}", 
						WebUtilidades.decimalFormat2Decimals.format(Double.parseDouble(WebUtilidades.trimToZero((String) register.get("valor_recibido")))));
				cuotas.append(cuotaTempXml);
			}
			
			fopXml = StringUtils.replace(fopXml, "${CUOTAS}", cuotas.toString());
			fopXml = StringUtils.replace(fopXml, "${FONT}", WebUtilidades.FONT);
			fopXml = StringUtils.replace(fopXml, "${CELLBORDER}", WebUtilidades.CELLBORDER);
			fopXml = StringUtils.replace(fopXml, "${CELLBORDER_NR}", WebUtilidades.CELLBORDER_NR);
			fopXml = StringUtils.replace(fopXml, "${CELLBORDER_NL}", WebUtilidades.CELLBORDER_NL);
			
			Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, byteArrayOutputStream);
			TransformerFactory factory = TransformerFactory.newInstance();
			Transformer transformer = factory.newTransformer();
			Source source = new StreamSource(new InputStreamReader(new ByteArrayInputStream(fopXml.getBytes()), "ISO-8859-1"));
			Result result = new SAXResult(fop.getDefaultHandler());
			transformer.transform(source, result);
			response.setContentType("application/pdf");
			response.setHeader("Content-Disposition", "inline; filename=\"RECIBO_PROVICIONAL.pdf\"");
			byteArrayOutputStream.writeTo(response.getOutputStream());
			return;
		} catch (FOPException e) {
			logger.error("Exception :", e);
		} catch (IOException e) {
			logger.error("Exception :", e);
		} catch (TransformerConfigurationException e) {
			logger.error("Exception :", e);
		} catch (TransformerException e) {
			logger.error("Exception :", e);
		} catch (WebException e) {
			try {
				response.setContentType("text/html");
				response.getWriter().write(e.getExceptionMessage());
				return;
			} catch (IOException e1) {
				logger.error("Exception: ", e1);
			}
		}
		try {
			response.setContentType("text/html");
			response.getWriter().write(WebUtilidades.PDF_ERROR);
		} catch (IOException e) {
			logger.error("Exception: ", e);
		}
	}

	@RequestMapping(value = "/deletePago", method = {RequestMethod.GET, RequestMethod.POST})
	public void deletePago(HttpServletResponse response, @RequestParam Long asgPagoId, @RequestParam Long asgClienteId) {
		Map<String, Object> result = new HashMap<String, Object>();
		try {
			DBContext.getAsgPagoService().deleteAsgPago(asgPagoId);
			result.put("pendientes", DBContext.getAsgAbonoDao().findAllPendientes(asgClienteId));
			result.put("pagos", DBContext.getAsgAbonoDao().findAllPagos(asgClienteId));
			result.put(SUCCESS, true);
			result.put(MESSAGE, UPDATED_DATA);
		} catch (WebException e) {
			logger.error("Exception: ", e);
			result.put(FAILURE, true);
			result.put(MESSAGE, e.getExceptionMessage());
		} catch (Exception e) {
			logger.error("Exception: ", e);
			result.put(FAILURE, true);
			result.put(MESSAGE, DEFAULT_ERROR_MESSAGE);
		}
		serializeObject(result, response);
	}
}
